package client

import (
	"context"
	"fmt"
	"log"
	"os"
	"runtime"
	"strings"
	"sync"
	"time"

	"hawkeye/config"
	"hawkeye/protocol"
	"hawkeye/utils"

	"github.com/panjf2000/gnet/v2"
)

// Client TCP客户端简化实现
type Client struct {
	config        *config.Config
	eng           gnet.Engine
	conn          gnet.Conn // 使用gnet.Conn
	connMutex     sync.RWMutex
	connected     bool
	stopChan      chan struct{}
	eventHandlers map[protocol.EventType]func(*protocol.Message)
	sequence      uint64
	sequenceMutex sync.Mutex
}

// NewClient 创建新的TCP客户端
func NewClient(cfg *config.Config) *Client {
	return &Client{
		config:        cfg,
		connected:     false,
		stopChan:      make(chan struct{}),
		eventHandlers: make(map[protocol.EventType]func(*protocol.Message)),
	}
}

// OnBoot 客户端启动时调用
func (c *Client) OnBoot(eng gnet.Engine) (action gnet.Action) {
	c.eng = eng
	log.Println("TCP客户端启动成功")
	return gnet.None
}

// OnShutdown 客户端关闭时调用
func (c *Client) OnShutdown(eng gnet.Engine) {
	log.Println("TCP客户端关闭")
	close(c.stopChan)
}

// OnOpen 连接建立时调用
func (c *Client) OnOpen(conn gnet.Conn) (out []byte, action gnet.Action) {
	c.connMutex.Lock()
	c.conn = conn
	c.connected = true
	c.connMutex.Unlock()

	log.Printf("成功连接到服务器: %s", conn.RemoteAddr().String())
	// 启动心跳
	go c.startHeartbeat()

	return nil, gnet.None
}

// OnClose 连接关闭时调用
func (c *Client) OnClose(conn gnet.Conn, err error) (action gnet.Action) {
	c.connMutex.Lock()
	c.connected = false
	c.conn = nil
	c.connMutex.Unlock()

	if err != nil {
		log.Printf("连接断开，错误: %v", err)
		// 每隔10秒重连
		go func() {
			for {
				select {
				case <-c.stopChan:
					return
				case <-time.After(10 * time.Second):
					err := c.Connect()
					if err != nil {
						log.Printf("重连失败: %v", err)
						continue
					}
					log.Println("重连成功")
					return
				}
			}
		}()
	} else {
		log.Printf("连接正常关闭")
	}

	return gnet.None
}

// OnTraffic 数据到达时调用
func (c *Client) OnTraffic(conn gnet.Conn) (action gnet.Action) {
	// 读取数据
	data, err := conn.Next(-1)
	if err != nil {
		log.Printf("读取数据失败: %v", err)
		return gnet.Close
	}

	if len(data) == 0 {
		return gnet.None
	}

	// 处理消息
	c.handleMessage(data)

	return gnet.None
}

// Connect 连接到服务器
func (c *Client) Connect() error {
	log.Println("连接中...")
	addr := fmt.Sprintf("%s:%d", c.config.Client.ServerHost, c.config.Client.ServerPort)

	// 使用gnet客户端连接
	client, err := gnet.NewClient(c,
		gnet.WithMulticore(false),
		gnet.WithTCPKeepAlive(time.Minute),
		gnet.WithSocketRecvBuffer(c.config.Server.ReadBufferSize),
		gnet.WithSocketSendBuffer(c.config.Server.WriteBufferSize),
		gnet.WithReusePort(true),
		gnet.WithTicker(true),
	)
	if err != nil {
		return fmt.Errorf("创建客户端失败: %v", err)
	}

	// 启动客户端
	err = client.Start()
	if err != nil {
		return fmt.Errorf("启动客户端失败: %v", err)
	}

	// 连接到服务器
	conn, err := client.Dial("tcp", addr)
	if err != nil {
		return fmt.Errorf("连接服务器失败: %v", err)
	}
	_ = conn

	return nil
}

// SendMessage 发送消息到服务器
func (c *Client) SendMessage(msg *protocol.Message) error {
	c.connMutex.RLock()
	defer c.connMutex.RUnlock()

	if !c.connected || c.conn == nil {
		return fmt.Errorf("未连接到服务器")
	}

	// 设置消息序列号和时间戳
	c.sequenceMutex.Lock()
	msg.Sequence = c.sequence
	c.sequence++
	msg.Timestamp = time.Now().UnixNano()
	c.sequenceMutex.Unlock()
	log.Println("发送消息:", msg)

	// 编码消息
	data, err := protocol.EncodeMessage(msg)
	if err != nil {
		return err
	}

	// 发送消息（使用AsyncWrite，第二个参数为nil回调）
	return c.conn.AsyncWrite(data, nil)
}

// OnTick 定时器触发时调用（gnet v2要求实现）
func (c *Client) OnTick() (delay time.Duration, action gnet.Action) {
	// 返回下一次tick的延迟时间
	return time.Second, gnet.None
}

// RegisterEventHandler 注册事件处理器
func (c *Client) RegisterEventHandler(eventType protocol.EventType, handler func(*protocol.Message)) {
	c.eventHandlers[eventType] = handler
}

// SendHeartbeat 发送心跳消息
func (c *Client) SendHeartbeat(clientID string) error {
	msg := protocol.NewHeartbeatMessage(clientID)
	return c.SendMessage(msg)
}

// SendAuth 发送认证消息
func (c *Client) SendAuth(token, userID string) error {
	msg := protocol.NewAuthMessage(token, userID)
	return c.SendMessage(msg)
}

// SendAuth 发送认证消息
func (c *Client) SendRegister() error {
	// 获取当前设备IP
	ipList, err := utils.GetLocalIPs()
	if err != nil {
		log.Fatal("获取本机IP失败")
	}
	var registerData protocol.RegisterData
	// ipList转str , 逗号分隔
	registerData.HostIP = strings.Join(ipList, ",")

	// 获取HostName
	hostName, err := os.Hostname()
	if err != nil {
		log.Fatal("获取主机名失败")

	}
	registerData.HostName = hostName
	// 获取OS类型
	registerData.OsType = runtime.GOOS
	// 获取CPU架构
	registerData.OSArch = runtime.GOARCH
	// 获取OS版本
	if registerData.OsType == "windows" {
		version, err := utils.GetWindowsVersion()
		if err != nil {
			log.Fatal("获取Windows版本失败")
		}
		registerData.OSVersion = version

	} else if registerData.OsType == "linux" {
		version, err := utils.GetLinuxVersion()
		if err != nil {
			log.Fatal("获取Linux版本失败")
		}
		registerData.OSVersion = version

	} else if registerData.OsType == "darwin" {
		version, err := utils.GetMacOSVersion()
		if err != nil {
			log.Fatal("获取MacOS版本失败")
		}
		registerData.OSVersion = version

	} else {
		log.Fatal("不支持的操作系统类型")
	}

	msg := protocol.NewRegisterMessage(registerData)
	return c.SendMessage(msg)
}

// Disconnect 断开连接
func (c *Client) Disconnect() {
	c.eng.Stop(context.Background())
}

// IsConnected 检查是否已连接
func (c *Client) IsConnected() bool {
	c.connMutex.RLock()
	defer c.connMutex.RUnlock()
	return c.connected
}

// handleMessage 处理接收到的消息
func (c *Client) handleMessage(data []byte) {
	// 解码消息
	msg, err := protocol.DecodeMessage(data)
	if err != nil {
		log.Printf("消息解码失败: %v", err)
		return
	}

	// 调用对应的事件处理器
	if handler, exists := c.eventHandlers[msg.Event]; exists {
		handler(msg)
	} else {
		log.Printf("未注册的事件处理器: %d", msg.Event)
	}
}

// startHeartbeat 启动心跳
func (c *Client) startHeartbeat() {
	ticker := time.NewTicker(c.config.Server.HeartbeatInterval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			if c.IsConnected() {
				c.SendHeartbeat("client_001") // 示例客户端ID
			}
		case <-c.stopChan:
			return
		}
	}
}
